package com.wyw.hemerocallis;

import com.wyw.hemerocallis.permission.PermissionClient;
import com.wyw.hemerocallis.vo.PermissionInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.List;

/**
 * 权限探测监听器 Spring容器启动之后自动运行
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
@Slf4j
@Component
public class PermissionDetectListener implements ApplicationListener<ApplicationReadyEvent> {
    private static final String KEY_SERVER_CTX = "server.servlet.context-path";
    private static final String KEY_SERVICE_NAME = "spring.application.name";

    @Override
    @SuppressWarnings("all")
    public void onApplicationEvent(ApplicationReadyEvent event) {
        ApplicationContext ctx = event.getApplicationContext();

        new Thread(() -> {

            // 扫描权限(注解)
            List<PermissionInfo> infoList = scanPermission(ctx);

            // 注册权限
            registerPermission(infoList, ctx);

        }).start();
    }

    /**
     * 注册接口权限
     */
    @SuppressWarnings("all")
    private void registerPermission(List<PermissionInfo> infoList,
                                    ApplicationContext ctx) {
        log.info("*************** register permission ***************");

        PermissionClient permissionClient =
                ctx.getBean(PermissionClient.class);

        if(null == permissionClient) {
            log.error("No permissionClient bean found");
            return;
        }

        //取出service name
        String servName = ctx.getEnvironment().getProperty(KEY_SERVICE_NAME);
        log.info("serviceName:{}", servName);

        boolean result = new PermissionRegistry(
                permissionClient, servName
        ).register(infoList);

        if (result) {
            log.info("*************** done register ***************");
        }
    }

    /**
     * 扫描微服务中的Controller接口权限信息
     */
    private List<PermissionInfo> scanPermission(ApplicationContext context) {
        //取出context的前缀信息
        String pathPrefix = context.getEnvironment().getProperty(KEY_SERVER_CTX);

        //取出Spring的映射bean   就是controller的映射   这个bean存在两个实现类，所以只能通过name获取
        RequestMappingHandlerMapping mappingBean =
                (RequestMappingHandlerMapping) context.getBean("requestMappingHandlerMapping");

        //扫描权限
        List<PermissionInfo> permissionInfoList =
                new AnnotationScanner(pathPrefix).scanPermission(
                        mappingBean.getHandlerMethods()
                );

        permissionInfoList.forEach(p -> log.info("{}", p));

        log.info("{} permission found", permissionInfoList.size());
        log.info("*************** done scanning ***************");

        return permissionInfoList;
    }

}
